package thread.state;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadWaitNotifyTest {
    static Object object = new Object();

    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy:mm:dd-hh:mm:ss:sss");

        Thread thread0 = new Thread() {
            @Override
            public void run() {
                System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + "Thread " + Thread.currentThread().getName() + " start");

                super.run();

                long startTime = System.currentTimeMillis();
                boolean waited = false;

                while ((System.currentTimeMillis() - startTime) < 2000) {

                    if (!waited && (System.currentTimeMillis() - startTime) > 1000) {
                        System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + " Thread " + Thread.currentThread().getName() + " wait() start");
                        waited = true;
                        waitOrNotify(true);

                        System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + " Thread " + Thread.currentThread().getName() + " wait() finish");
                    }
                }

                System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + "Thread " + Thread.currentThread().getName() + " end");
            }
        };

        Thread thread1 = new Thread() {
            @Override
            public void run() {
                System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + "Thread " + Thread.currentThread().getName() + " start");

                super.run();

                long startTime = System.currentTimeMillis();
                boolean notified = false;

                while ((System.currentTimeMillis() - startTime) < 3000) {

                    if (!notified && (System.currentTimeMillis() - startTime) > 2000) {
                        notified = true;

                        waitOrNotify(false);

                        System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + " Thread " + Thread.currentThread().getName() + " notify()");
                    }
                }

                System.out.println(simpleDateFormat.format(new Date(System.currentTimeMillis())) + "Thread " + Thread.currentThread().getName() + " start");
            }
        };

        thread0.start();
        thread1.start();
    }


    static void waitOrNotify(boolean wait) {
        synchronized (object) {
            if (wait) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                object.notify();
            }
        }
    }
}
